package pl.edu.agh.ssm.monitor.listeners;

import java.util.HashMap;

import pl.edu.agh.ssm.monitor.SessionMonitorApp;
import pl.edu.agh.ssm.monitor.data.Packet; //import pl.edu.agh.ssm.monitor.data.RTSPAnswer;
import pl.edu.agh.ssm.monitor.data.RTSPPacket;
import pl.edu.agh.ssm.monitor.data.RTSPPacketType;
import pl.edu.agh.ssm.monitor.data.Session;
import pl.edu.agh.ssm.monitor.data.SessionConnection;
import pl.edu.agh.ssm.monitor.data.SessionDataContainer;
import pl.edu.agh.ssm.monitor.data.SessionDescription;
import pl.edu.agh.ssm.monitor.data.SessionMedia;
//import pl.edu.agh.ssm.monitor.data.SessionMediaState;
import pl.edu.agh.ssm.monitor.data.SessionMediaType;
import pl.edu.agh.ssm.monitor.data.SessionNode;
import pl.edu.agh.ssm.monitor.data.SessionNodeType;
import pl.edu.agh.ssm.monitor.data.SessionType;
import pl.edu.agh.ssm.monitor.net.PacketFilter;
import pl.edu.agh.ssm.monitor.net.PacketReceiver;
import pl.edu.agh.ssm.monitor.parsers.rtsp.InvalidRTSPDataException; //import pl.edu.agh.ssm.monitor.parsers.rtsp.RTSPAnswerParser;
import pl.edu.agh.ssm.monitor.parsers.rtsp.RTSPParser;
//import pl.edu.agh.ssm.monitor.utils.PacketListenersUtils;

public class RTSPSessionListener implements PacketListener {

	private int priority;
	private PacketReceiver receiver;
	private SessionDataContainer<Session> sessions = null;
	private RTSPAnswersListener answersListener = null;

	public RTSPSessionListener(PacketReceiver receiver) {
		this.receiver = receiver;
		sessions = SessionMonitorApp.getApplication().getManager()
				.createContainer(Session.class);
	}

	@Override
	public void processPacket(Packet packet) {

		// System.out
		// .println("---------------------------------START
		// PACKET--------------------------------");
		RTSPParser parser = new RTSPParser();
		try {
			// System.out.println("Try to parse RTSP packet");
			RTSPPacket rtspPacket = parser.parse(packet.getData());
			// System.out.println("Packet sucessfully parsed: "
			// + rtspPacket.getType());
			// System.out.println(rtspPacket.getPacketContent());
			Session currentSession = sessions.get(getSessionID(packet));
			// System.out.println("Try to find session: " +
			// getSessionID(packet));
			if (currentSession == null) {
				currentSession = new Session(getSessionID(packet));
				currentSession.setSessionType(SessionType.RTSP_SESSION);
				currentSession.setSessionDesc(getSessionID(packet));
				SessionDescription desc = new SessionDescription();
				desc.setName("RTSP Session : "
						+ packet.getDestAddress().getHostAddress());
				currentSession.setSessionDescription(desc);
				sessions.add(currentSession);

				// add streaming server
				SessionNode server = new SessionNode(packet.getDestAddress(),
						currentSession.getId());
				server.setNodeType(SessionNodeType.SERVER);
				currentSession.addNode(server);
				// add client
				SessionNode client = new SessionNode(packet.getSourceAddress(),
						currentSession.getId());
				client.setNodeType(SessionNodeType.RECEIVER);
				currentSession.addNode(client);
				// add connection
				SessionConnection connection = new SessionConnection(server,
						client, currentSession.getId());
				connection.setConnectionAddress(packet.getSourceAddress());
				connection.setConnectionPort(packet.getSourcePort());
				SessionMedia mediaDesc = new SessionMedia(
						SessionMediaType.RTSP_CONTROL, "RTSP Control channel",
						0);
				connection.setMediaDesc(mediaDesc);
				currentSession.addConnection(connection);
				setUpAnswersListener(packet, currentSession, connection);
				// } else {
				// System.out.println("Session found");
			}
			// System.out.println("Before get connection");
			/* Add rtsp packet to session connection */

			getConnection(packet, rtspPacket).addRtspPacket(rtspPacket);
			// System.out.println("After get connection");
			/* Check packet type and do appropriate action */
//			if (rtspPacket.getType().compareTo(RTSPPacketType.PLAY) == 0) {
//				System.out.println("PLAY packet");
//				getConnection(packet, rtspPacket).getMediaDesc().setMediaState(
//						SessionMediaState.PLAY);
//			}
//			if (rtspPacket.getType() == RTSPPacketType.PAUSE) {
//				System.out.println("PAUSE packet");
//				getConnection(packet, rtspPacket).getMediaDesc().setMediaState(
//						SessionMediaState.PAUSE);
//			}
			if (rtspPacket.getType() == RTSPPacketType.TEARDOWN) {
//				System.out.println("TEARDOWN packet");
//				getConnection(packet, rtspPacket).getMediaDesc().setMediaState(
//						SessionMediaState.TEARDOWN);
				if (answersListener != null) {
					answersListener.removeAllListeners();
				}

			}

			currentSession.updateConnection(getConnection(packet, rtspPacket));
		} catch (InvalidRTSPDataException e) {

			// e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		// System.out
		// .println("----------------------------------END
		// PACKET---------------------------------");
		// System.out.println();
	}

	@Override
	public int getPriority() {
		return priority;
	}

	@Override
	public void setPriority(int priority) {
		this.priority = priority;
	}

	private String getSessionID(Packet packet) {
		return new String("RTSP: " + packet.getSourceAddress().getHostAddress()
				+ ":" + packet.getSourcePort() + "-"
				+ packet.getDestAddress().getHostAddress() + ":"
				+ packet.getDestPort());
	}

	private void setUpAnswersListener(Packet packet, Session currentSession,
			SessionConnection connection) {
//		System.out.println("SETUP ANSWERS LISTENER CALLED");
		PacketFilter filter = new PacketFilter();
		filter.setAddress(packet.getSourceAddress().getHostAddress());
		filter.setPort(packet.getSourcePort());
		filter.setSourcePort(554); // rtsp port
		HashMap<Integer, SessionMedia> rtpmap = null;
		if (currentSession.getSessionDescription() != null) {
			rtpmap = currentSession.getSessionDescription().getRtpmap();
		}
		answersListener = new RTSPAnswersListener(sessions, currentSession,
				connection, this.receiver, rtpmap);
		receiver.addPacketListenerToSession(answersListener, filter, currentSession.getId());
	}

	private SessionConnection getConnection(Packet packet, RTSPPacket rtspPacket) {
		// System.out.println("Get session");
		Session session = sessions.get(getSessionID(packet));
		// System.out.println("Get connection");
		if (session != null) {
			for (SessionConnection connection : session.getConnections()
					.getAll()) {
				if (connection.getConnectionAddress().getHostName()
						.equalsIgnoreCase(
								packet.getSourceAddress().getHostName())
						&& connection.getConnectionPort() == packet
								.getSourcePort()) {
					return connection;
				}
			}
		}
		return null;
	}

	// private SessionConnection createConnection(Packet )

	// private Session getSession(long sessionID) {
	// return null;
	// }
}
